﻿#include "Matrix4x4.h"
#include "../Misc.h"
#include "bMath.h"

namespace Base {
	bool Matrix4x4::Decompose(Vec3& t, Quaternion& r, Vec3& s) const {
		XMVECTOR vs, vt, vr;
		bool success = XMMatrixDecompose(&vs, &vr, &vt, XMLoadFloat4x4(&data));
		if (success) {
			XMStoreFloat3(&t.data, vt);
			XMStoreFloat4(&r.data, vr);
			XMStoreFloat3(&s.data, vs);
		}
		else {
			Debug::ThrowOrMessageBox("====> [Matrix4x4->Decompose] Failed!");
		}
		return success;
	}

	// static
	Matrix4x4 Matrix4x4::TRS(const Vec3&  t, const Quaternion& r, const Vec3& s) {
		auto matT = Matrix4x4::CreateTranslation(t);
		auto matR = QuaternionToMatrix4x4(r);
		auto matS = Matrix4x4::CreateScale(s);
		return matS * matR * matT;
	}

	Matrix4x4 Matrix4x4::CreateTranslation(float x, float y, float z) {
		Matrix4x4 result;
		XMStoreFloat4x4(&result.data, XMMatrixTranslation(x, y, z));
		return result;
	}
	Matrix4x4 Matrix4x4::CreateTranslation(const Vec3& v) {
		return CreateTranslation(v.x, v.y, v.z);
	}

	Matrix4x4 Matrix4x4::CreateScale(float sx, float sy, float sz) {
		Matrix4x4 result;
		XMStoreFloat4x4(&result.data, XMMatrixScaling(sx, sy, sz));
		return result;
	}
	Matrix4x4 Matrix4x4::CreateScale(const Vec3& v) {
		return CreateScale(v.x, v.y, v.z);
	}

	// 绕X轴旋转(弧度，从X轴正方向朝原点看顺时针)矩阵
	Matrix4x4 Matrix4x4::CreateRotationX(float rad) {
		Matrix4x4 result;
		XMStoreFloat4x4(&result.data, XMMatrixRotationX(rad));
		return result;
	}

	Matrix4x4 Matrix4x4::CreateRotationY(float rad) {
		Matrix4x4 result;
		XMStoreFloat4x4(&result.data, XMMatrixRotationY(rad));
		return result;
	}

	Matrix4x4 Matrix4x4::CreateRotationZ(float rad) {
		Matrix4x4 result;
		XMStoreFloat4x4(&result.data, XMMatrixRotationZ(rad));
		return result;
	}

	/*
		按照先绕Z轴，然后X轴，最后Y轴的顺序得到旋转矩阵(弧度)
		结果与下面的矩阵 m 相同
		Matrix4x4 r1 = Matrix4x4::CreateRotationZ(roll);
		Matrix4x4 r2 = Matrix4x4::CreateRotationX(pitch);
		Matrix4x4 r3 = Matrix4x4::CreateRotationY(yaw);
		Matrix4x4 m = r1 * r2 * r3;
	 */
	Matrix4x4 Matrix4x4::CreateRollPitchYaw(float pitch, float yaw, float roll) {
		Matrix4x4 result;
		XMStoreFloat4x4(&result.data, XMMatrixRotationRollPitchYaw(pitch, yaw, roll));
		return result;
	}

	// 按照 Z-X-Y 顺序,创造一个旋转矩阵
	Matrix4x4 Matrix4x4::CreateRotation(float x, float y, float z) {
		Matrix4x4 result;
		XMStoreFloat4x4(&result.data, XMMatrixRotationRollPitchYaw(x, y, z));
		return result;
	}

	// 返回  (lhs * rhs).Transpose();
	Matrix4x4 Matrix4x4::MatrixMultiplyTranspose(const Matrix4x4& lhs, const Matrix4x4& rhs) {
		Matrix4x4 result;
		XMStoreFloat4x4(&result.data, XMMatrixMultiplyTranspose(XMLoadFloat4x4(&lhs.data), XMLoadFloat4x4(&rhs.data)));
		return result;
	}


	// 由轴-角得到旋转矩阵  
	Matrix4x4 Matrix4x4::CreateRotationFromAxisAngle(const Vec3& normalizeAxis, float rad) {
		Matrix4x4 result;
		XMStoreFloat4x4(&result.data, XMMatrixRotationNormal(XMLoadFloat3(&normalizeAxis.data), rad));
		return result;
	}


	// TODO:等待验证
	// 由四元数 创建 旋转矩阵

	Matrix4x4 Matrix4x4::CreatePerspectiveFovLH(float rad, float aspect, float near, float far) {
		Matrix4x4 result;
		XMStoreFloat4x4(&result.data, XMMatrixPerspectiveFovLH(rad, aspect, near, far));
		return result;
	}

	Matrix4x4 Matrix4x4::CreateLookAtLH(const Vec3& pos, const Vec3& target, const Vec3& up) {
		Matrix4x4 result;
		XMStoreFloat4x4(&result.data, XMMatrixLookAtLH(XMLoadFloat3(&pos.data), XMLoadFloat3(&target.data), XMLoadFloat3(&up.data)));
		return result;
	}

	// TODO: 等待实现
	// 1. XMMatrixReflect
	// 2. XMMatrixShadow
	// 3. XMMatrixLookAtLH
	// 5. XMVector3Project  
	// 6. XMVector3Unproject
}